package com.iwhalecloud.bss.kite.cucc.web.controller.scene;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import com.iwhalecloud.bss.kite.dataservice.cache.ProdFeeAttrCache;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.iwhalecloud.bss.kite.client.api.scene.operate.IOperateSceneAdditionalOfferInstService;
import com.iwhalecloud.bss.kite.client.api.scene.query.IQuerySceneAdditionalOfferInstService;
import com.iwhalecloud.bss.kite.client.api.scene.query.IQuerySceneCommonService;
import com.iwhalecloud.bss.kite.client.api.scene.query.IQuerySceneMainOfferInstService;
import com.iwhalecloud.bss.kite.client.dto.DataResult;
import com.iwhalecloud.bss.kite.client.dto.inst.InstAttrDTO;
import com.iwhalecloud.bss.kite.client.dto.inst.OfferInstDTO;
import com.iwhalecloud.bss.kite.client.dto.rule.common.DataRuleResult;
import com.iwhalecloud.bss.kite.client.dto.rule.common.RuleConsts;
import com.iwhalecloud.bss.kite.client.vo.scene.ProdSubOfferVO;
import com.iwhalecloud.bss.kite.common.callclient.service.rule.IRuleTriggerService;
import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteDateUtils;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteMapUtils;
import com.iwhalecloud.bss.kite.common.util.KiteObjectUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.common.util.RuleResponseUtils;
import com.iwhalecloud.bss.kite.cucc.client.api.goods.ILocalAddtionOfferService;
import com.iwhalecloud.bss.kite.cucc.client.api.rule.check.ICuccCheckService;
import com.iwhalecloud.bss.kite.cucc.client.service.cache.ILocalRefreshCacheService;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.CuccOfferVO;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.CuccPayAddtionOfferVO;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.CuccProdSubOfferVO;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.DeleteAdditionalOfferListParamVO;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.OptionalAdditionalOfferModuleVO;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.WholeQuickEntryVO;
import com.iwhalecloud.bss.kite.cucc.common.constant.CuccServiceOfferConsts;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalDcPublicConsts;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalKeyConsts;
import com.iwhalecloud.bss.kite.cucc.common.util.DateFormatUtils;
import com.iwhalecloud.bss.kite.cucc.common.util.DecimalCalc;
import com.iwhalecloud.bss.kite.cucc.service.cache.LocalWholeQuickEntryCache;
import com.iwhalecloud.bss.kite.cucc.service.util.ProdCateUtil;
import com.iwhalecloud.bss.kite.cucc.web.service.accept.handler.module.OptionalAdditionalOfferModuleHandler;
import com.iwhalecloud.bss.kite.cucc.web.service.accept.handler.module.ShutdownAdditionalOfferModuleHandler;
import com.iwhalecloud.bss.kite.cucc.web.service.accept.util.LocalAdditionalOfferUtils;
import com.iwhalecloud.bss.kite.dataservice.cache.DcPublicCache;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferDetailCache;
import com.iwhalecloud.bss.kite.dataservice.cache.ProdFeeCache;
import com.iwhalecloud.bss.kite.dataservice.entity.DcPublic;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.Offer;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.OfferDetail;
import com.iwhalecloud.bss.kite.manager.api.IOperateSceneInstService;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.enums.RelType;
import com.iwhalecloud.bss.kite.manager.inst.KiteAttr;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteSceneInst;
import com.iwhalecloud.bss.kite.manager.transaction.KiteTransactional;
import com.iwhalecloud.bss.kite.service.util.CopyToDtoUtil;
import com.iwhalecloud.bss.kite.web.context.KiteWebContext;
import com.iwhalecloud.bss.kite.web.service.accept.util.AdditionalOfferUtils;
import com.iwhalecloud.bss.kite.web.util.RuleParamUtils;
import com.ztesoft.bss.common.bo.LoginInfo;
import com.ztesoft.bss.common.util.ContextUtil;
import com.ztesoft.bss.common.util.SpringUtil;
import com.ztesoft.bss.order.base.orm.conf.BusiConfigTables;
import com.ztesoft.bss.rul.core.client.dto.common.RuleCommonParam;
import com.ztesoft.bss.rul.core.client.dto.instspec.InstAttrChange;
import com.ztesoft.bss.rul.core.client.dto.kite.KiteRuleResponse;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

/**
 * <Description> 可选包操作 <br>
 *
 * @author huang.caibiao<br>
 * @version 1.0<br>
 * @see com.iwhalecloud.bss.kite.web.controller.order <br>
 * @since R9.0<br>
 */
@SuppressWarnings("deprecation")
@RestController
@RequestMapping("/CuccAdditionalOffer")
@Api(tags = {"/CuccAdditionalOffer - 可选包"
})
public class CuccAdditionalOfferController {

    @Autowired
    private IQuerySceneInstService querySceneInstService;

    @Autowired
    private IOperateSceneAdditionalOfferInstService operateSceneAdditionalOfferInstService;
    @Autowired
    private IRuleTriggerService ruleTriggerService;
    @Autowired
    private IQuerySceneMainOfferInstService querySceneMainOfferInstService;

    @Autowired
    private IQuerySceneCommonService querySceneCommonService;

    @Autowired
    private IQuerySceneAdditionalOfferInstService querySceneAdditionalOfferInstService;

    @Autowired
    IOperateSceneInstService sceneInstOperateService;

    @Autowired
    ILocalAddtionOfferService localAddtionOfferService;


    @Autowired
    private ICuccCheckService cuccCheckService;

    @KiteTransactional
    @ApiOperation(value = "联通添加可选包", notes = "联通添加可选包")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "offerId", value = "可选包标识", required = true),
        @ApiImplicitParam(name = "type", value = "约束类型,0：产品约束，1：销售品约束", required = true),
        @ApiImplicitParam(name = "offerInstId", value = "销售品实例Id", required = true)
    })
    @PostMapping(value = "/addCuccAdditional")
    public DataResult<CuccProdSubOfferVO> saveCuccAdditionalOffer(@RequestParam String offerId, @RequestParam String type, @RequestParam String offerInstId) {
        //可选包挂靠的为单商品
        KiteProdInst kiteProdInst = null;
        String custId = KiteWebContext.getContext().getCustId();
        List<KiteProdInst> prodInstsFromMain = querySceneInstService.listProdInstsFromOfferInst(custId, offerInstId);
        if (KiteListUtils.isNotEmpty(prodInstsFromMain)) {
            kiteProdInst = prodInstsFromMain.get(0);
        } else {
            kiteProdInst = querySceneInstService.listProdInstsFromOfferInst(custId, offerInstId).get(0);
        }

        return addCuccAdditionalOffer(kiteProdInst.getProdInstId(), offerId, offerInstId, type, true);
    }


    private DataResult<CuccProdSubOfferVO> addCuccAdditionalOffer(String prodInstId, String offerId, String offerInstId, String type, boolean addOnly) {
        String sceneInstId = KiteWebContext.getContext().getCurrentSceneInstId();
        String custId = KiteWebContext.getContext().getCustId();
        LoginInfo loginInfo = ContextUtil.getLoginInfo();
        String staffId = loginInfo.getUserInfo().getUserId() + "";
        // 资费产品的属性不存在的时候，重新加载一次缓存
        Offer offer = ProdFeeCache.get(offerId);
        KiteOfferInst mainOfferInst = querySceneInstService.getOfferInst(custId, offerInstId);
        if (KiteListUtils.isEmpty(ProdFeeAttrCache.get(offerId, mainOfferInst.getOfferId(), ContextUtil.getLoginInfo().getUserInfo().getPostProvinceNbr()))) {
            SpringUtil.getBean(ILocalRefreshCacheService.class).refreshAdditionalOfferCache(mainOfferInst.getOfferId());
        }

        OfferInstDTO offerInstDTO = null;
        //产品约束的可选包
        if (KeyConsts.ADDITIONAL_PRODUCT_TYPE.equals(type)) {

            if (addOnly) {
                offerInstDTO = operateSceneAdditionalOfferInstService
                    .addAdditionalOfferOfProduct(sceneInstId, prodInstId, offerId, custId, staffId, true).getResultObject();
            } else {
                offerInstDTO = operateSceneAdditionalOfferInstService
                    .addAdditionalOfferOfProduct(sceneInstId, prodInstId, offerId, custId, staffId).getResultObject();
            }

        } else if (KeyConsts.ADDITIONAL_OFFER_TYPE.equals(type)) {
            OfferInstDTO offerInst = querySceneMainOfferInstService.getSceneMainOfferInstByProdInstId(sceneInstId, prodInstId, custId).getResultObject();
            if (offerInst == null) {
                offerInst = querySceneCommonService
                    .getSceneOfferInstByOfferInstId(sceneInstId, offerInstId, custId).getResultObject();
            }

            offerInstId = offerInst.getOfferInstId();

            offerInstDTO = operateSceneAdditionalOfferInstService
                .addAdditionalOffer(sceneInstId, offerInstId, prodInstId, offerId, custId, staffId).getResultObject();

            //处理可选包与产品实例之间的关系，因后续的明细处理事件的max不可控，可能导致没添加关系
            KiteProdInst prodInst = querySceneInstService.getProdInst(custId, prodInstId);
            OfferDetail additionalOfferDetail = OfferDetailCache.get(offerInstDTO.getOfferId()).stream().filter(offerDetail -> {
                return offerDetail.getObjId().equals(prodInst.getProdId());
            }).findFirst().orElse(null);
            if (!KiteObjectUtils.isEmpty(additionalOfferDetail)) {
                sceneInstOperateService.addOfferObjInstRel(sceneInstId, InstType.ADDITIONAL_OFFER_INST, offerInstDTO.getOfferInstId(),
                    prodInst.getInstType(), prodInstId, RelType.OFFER_OBJ_REL_TYPE_1000, ActionType.A,
                    additionalOfferDetail.getRoleId(), additionalOfferDetail.getDetailId(), KiteWebContext.getContext().getCustId());
            }
        }

        if (Objects.nonNull(offerInstDTO)) {
            ProdSubOfferVO prodSubOfferVO = AdditionalOfferUtils.getInst().genProdSubOfferVO(offerInstDTO, null, null);
            CuccProdSubOfferVO cuccProdSubOfferVO = KiteBeanUtils.transform(prodSubOfferVO, CuccProdSubOfferVO.class);
            cuccProdSubOfferVO.setAccessProdInstId(prodInstId);
            cuccProdSubOfferVO.setPayType(KiteMapUtils.getString(offer.getOfferMap(), "payType"));

            //过滤掉以category配置的offer_attr属性，showType为O的
            List<InstAttrDTO> instAttrDTOList = new ArrayList<>();
            querySceneAdditionalOfferInstService.listAdditionalOfferInstAttrsByOfferInstId(sceneInstId, offerInstDTO.getOfferInstId(),
                KiteWebContext.getContext().getCustId()).getResultObject().forEach(instAttrDTO -> {
                if (instAttrDTO.getShowType().equals(LocalKeyConsts.KITE_ATTR_CONFIG_SHOW_TYPE_D) || instAttrDTO.getShowType().equals(LocalKeyConsts.KITE_ATTR_CONFIG_SHOW_TYPE_M)) {
                    //todo 可选包先放开属性的不可编辑
//                    instAttrDTO.setIsEdit(KeyConsts.IFTRUE_T);
                    instAttrDTOList.add(instAttrDTO);
                }
            });
            cuccProdSubOfferVO.setInstAttrDTOS(instAttrDTOList);
            DataResult<CuccProdSubOfferVO> result = ErrorConsts.SUCCESS
                .getResult(cuccProdSubOfferVO);
            return result;
        }

        return null;
    }

    /**
     * 返回结果中的子数据集合中 添加一个新的字段
     *
     * @param cuccOfferVOS
     * @return
     */
    private List<CuccPayAddtionOfferVO> getNew5GResult(List<CuccPayAddtionOfferVO> cuccOfferVOS) {
        List<CuccPayAddtionOfferVO> rsCuccOfferVOS = new ArrayList<CuccPayAddtionOfferVO>();
        if (KiteListUtils.isNotEmpty(cuccOfferVOS)) {
            for (int i = 0; i < cuccOfferVOS.size(); i++) {
                CuccPayAddtionOfferVO cuccPayAddtionOfferVO = cuccOfferVOS.get(i);
                List<CuccOfferVO> offerVOList = cuccPayAddtionOfferVO.getOfferVOList();
                List<CuccOfferVO> newOfferVOList = new ArrayList<CuccOfferVO>();
                for (int j = 0; j < offerVOList.size(); j++) {
                    CuccOfferVO cuccOfferVO = new CuccOfferVO();
                    cuccOfferVO = offerVOList.get(j);
                    String offerId = cuccOfferVO.getOfferId();
                    // 5G专网产品
                    List<DcPublic> dcList = DcPublicCache.getByPkey(LocalDcPublicConsts.DC_20210520401, offerId);
                    if (KiteListUtils.isNotEmpty(dcList)) {
                        // 一次性资费 安装调测-100000000017339、运营增值服务-100000000017337、覆盖增强服务-100000000017334
                        if (KiteStringUtils.equalsAny(offerId, "100000000017339", "100000000017337", "100000000017334")) {
                            cuccOfferVO.setPromptMessage("注：一次性费用若存分段。会收多次费用,请确保受理时只填入一段资表");
                        } else {
                            cuccOfferVO.setPromptMessage("注：本月租资费生效时间以起租时间更新回填，前台录入时间不等于起租时间");
                        }
                        newOfferVOList.add(cuccOfferVO);
                    } else {
                        // 非5G专网产品时，直接返回
                        return cuccOfferVOS;
                    }
                }
                cuccPayAddtionOfferVO.setOfferVOList(newOfferVOList);
                rsCuccOfferVOS.add(cuccPayAddtionOfferVO);
            }
            return rsCuccOfferVOS;
        } else {
            return cuccOfferVOS;
        }
    }

    @KiteTransactional
    @ApiOperation(value = "添加资费", notes = "查询可订购资费列表")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "offerInstId", value = "销售品实例Id", required = true)
    })
    @GetMapping(value = "/addAdditionalOfferList")
    public DataResult<List<CuccPayAddtionOfferVO>> addAdditionalOfferList(@RequestParam String offerInstId,
                                                                          @RequestParam(value = "checked", required = false, defaultValue = "1") Integer checked,
                                                                          @RequestParam(value = "feeTypeCode", required = false, defaultValue = "1") String feeTypeCode) {
        String custId = KiteWebContext.getContext().getCustId();
        String sceneInstId = KiteWebContext.getContext().getCurrentSceneInstId();
        String staffId = KiteStringUtils.valueOf(ContextUtil.getUserId());
        List<CuccPayAddtionOfferVO> cuccOfferVOS = LocalAdditionalOfferUtils.getInst().getOptionalAdditionalOfferListWithOutInst(sceneInstId, custId, offerInstId, staffId, checked, feeTypeCode);
        cuccOfferVOS = getNew5GResult(cuccOfferVOS);

        boolean isMultipleCharge = false;
        KiteOfferInst offerInst = querySceneInstService.getOfferInst(custId, offerInstId);
        if (ProdCateUtil.getDoubleLineOfferId().contains(offerInst.getOfferId())) {
            // 五大双线基础产品，获取【是否多方收费】属性值
            KiteProdInst kiteProdInst = querySceneInstService.listProdInstsFromOfferInst(custId, offerInstId).get(0);
            isMultipleCharge = KiteStringUtils.isEqual(kiteProdInst.getAttrValue("210008004"), "1_0000106");

            cuccOfferVOS.forEach(cuccOfferVO -> {
                if (KiteListUtils.isNotEmpty(cuccOfferVO.getOfferVOList())
                    && KiteStringUtils.equalsAny(cuccOfferVO.getOfferVOList().get(0).getPayType(), "monthly-charge", "one-time-charge")) {
                    cuccOfferVO.setFeeTypeCode("2");
                    cuccOfferVO.setFeeTypeName("收费方资费");
                } else {
                    cuccOfferVO.setFeeTypeCode("1");
                    cuccOfferVO.setFeeTypeName("发起方资费");
                }
            });
        }
        if (isMultipleCharge) {
            // 是否多方收费=是，不显示全程协议价快捷录入
            cuccOfferVOS.forEach(cuccOfferVO -> cuccOfferVO.setWholeQuickEntryVO(null));
        } else if (cuccOfferVOS.size() > 0) {
            //资费订购全城议价快捷录入
            LocalAdditionalOfferUtils.getInst().setWholeQuickEntryVO(cuccOfferVOS, sceneInstId, checked);
        }
//        cuccOfferVOS = LocalAdditionalOfferUtils.getInst().getNewJPWResult(cuccOfferVOS,offerInstId,sceneInstId,staffId);
        // 五大双线，资费展示排序，月租资费、一次性资费、包周期资费，目前按 categoryId 排除满足要求
        String cateId = Optional.ofNullable(offerInst.getAttrValue("cateId")).orElse("");
        if (ProdCateUtil.getDoubleLineCateId().contains(cateId)) {
            cuccOfferVOS = cuccOfferVOS.stream().sorted(Comparator.comparing(CuccPayAddtionOfferVO::getCategoryId)).collect(Collectors.toList());
        }
        return ErrorConsts.SUCCESS.getResult(cuccOfferVOS);
    }

    @ApiOperation(value = "获取资费属性列表", notes = "资费修改时，获取资费属性列表")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "offerInstId", value = "销售品实例Id", required = true),
        @ApiImplicitParam(name = "isPrview", value = "是否预览"),
        @ApiImplicitParam(name = "isEdit", value = "是否点击编辑", required = false)
    })
    @GetMapping(value = "/listAdditionalOfferInstAttrs")
    public DataResult<CuccProdSubOfferVO> listAdditionalOfferInstAttrs(@RequestParam String offerInstId, String isPrview, String isEdit) {
        String sceneInstId = KiteWebContext.getContext().getCurrentSceneInstId();
        String custId = KiteWebContext.getContext().getCustId();
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId, custId);
        String cateId = querySceneInstService.getOfferInstAttrValue(custId, sceneInst.getRootInstId(), "cateId");
        DcPublic JPCateIdDc = DcPublicCache.get("20210903104801").stream().findFirst().orElse(null);
        String JPCateId = Objects.nonNull(JPCateIdDc) ? JPCateIdDc.getPkey() : null;
        KiteOfferInst offerInst = querySceneInstService.getOfferInst(custId, offerInstId);
        OfferInstDTO offerInstDTO = KiteBeanUtils.transform(offerInst, OfferInstDTO.class);
        ProdSubOfferVO prodSubOfferVO = AdditionalOfferUtils.getInst().genProdSubOfferVO(offerInstDTO, null, null);
        CuccProdSubOfferVO cuccProdSubOfferVO = KiteBeanUtils.transform(prodSubOfferVO, CuccProdSubOfferVO.class);

        List<KiteAttr> kiteAttrList = offerInst.listAttrs();
        List<InstAttrDTO> dtoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(kiteAttrList)) {
            if (KiteStringUtils.isEqual(isEdit, KeyConsts.IFTRUE_T)) {
                IOperateSceneInstService operateSceneInstService = SpringUtil.getBean(IOperateSceneInstService.class);
                operateSceneInstService.putExtParameter(sceneInstId, offerInstId, kiteAttrList);
            }

            dtoList = CopyToDtoUtil.transInstAttrDtoList(kiteAttrList);
        }
        Map<String, Object> offerMap = ProdFeeCache.get(offerInst.getOfferId()).getOfferMap();
        String payType = KiteMapUtils.getString(offerMap, "payType");
        String nodeCode = querySceneInstService.getExtParameterValue(sceneInstId, "nodeCode");
        List<InstAttrDTO> instAttrDTOList = new ArrayList<>();
        String payStatus = cuccProdSubOfferVO.getStatus();
        dtoList.forEach(instAttrDTO -> {
            if (KiteStringUtils.equalsAny(instAttrDTO.getShowType(), LocalKeyConsts.KITE_ATTR_CONFIG_SHOW_TYPE_D, LocalKeyConsts.KITE_ATTR_CONFIG_SHOW_TYPE_M)) {
                if (KiteStringUtils.isEqual("T", isPrview)) {
                    instAttrDTO.setAttrValueTypeId("TT");
                }
                if (KiteStringUtils.isEqual(isEdit, KeyConsts.IFTRUE_T)) {
                    if (KiteStringUtils.equalsAny(offerInst.getActionType().name(), ActionType.K.name(), ActionType.M.name())) {
                        //actionType为不变和变更时，只能修改失效时间,失效模式
                        // 预销户需要对趸交资费进行处理
                        if (KiteStringUtils.isEqual(CuccServiceOfferConsts.SERVICE_OFFER_ACCOUNT_CANCEL, sceneInst.getServiceOfferId())) {
                            if (KiteStringUtils.equalsAny(instAttrDTO.getFieldName(), "200001735", "200000173")) {
                                instAttrDTO.setIsEdit(KeyConsts.IFTRUE_F);
                            }
                        }
                        else {
                          //加判断精品网可以修改折扣
                            if (KiteStringUtils.equalsAny(instAttrDTO.getFieldName(), "200000173", "200001735") || (KiteStringUtils.equals(cateId, JPCateId) && KiteStringUtils.equals(instAttrDTO.getFieldName(), "200001352"))) {
                                instAttrDTO.setIsEdit(KeyConsts.IFTRUE_T);
                                instAttrDTO.setShowType(LocalKeyConsts.KITE_ATTR_CONFIG_SHOW_TYPE_D);
                            } else {
                                instAttrDTO.setIsEdit(KeyConsts.IFTRUE_F);
                            }
                            //如果是失效资费 只允许修改失效时间不允许修改失效模式
                            if (KiteStringUtils.equals(instAttrDTO.getFieldName(), "200001735") && KiteStringUtils.equals("INVALID", payStatus)) {
                                instAttrDTO.setIsEdit(KeyConsts.IFTRUE_F);
                            }
                        }
                    }
                    //起租界面一次性资费价格、非一次性资费协议月租不允许编辑
                    if ("OrderStartRent".equals(nodeCode)) {
                        if ("200002509".equals(instAttrDTO.getFieldName())) {
                            KiteAttr firstMonthPayWay = offerInst.getAttr("200000170");
                            //不存在首月收取方式属性的资费认为是一次性资费
                            if (Objects.isNull(firstMonthPayWay)) {
                                instAttrDTO.setIsEdit(KeyConsts.IFTRUE_F);
                            }
                        }
                        if ("200000169".equals(instAttrDTO.getFieldName())) {
                            instAttrDTO.setIsEdit(KeyConsts.IFTRUE_F);
                        }
                        if (ProdCateUtil.getDoubleLineCateId().contains(cateId)) {
                            if ("200000170".equals(instAttrDTO.getFieldName())) {
                                instAttrDTO.setIsEdit(KeyConsts.IFTRUE_F);
                            }
                            if ("200000171".equals(instAttrDTO.getFieldName())) {
                                instAttrDTO.setIsEdit(KeyConsts.IFTRUE_F);
                            }
                        }
                        // 起租环节，只能编辑生效时间
                        if (LocalKeyConsts.FEE_PAY_TYPE_ONE_OFF.equals(payType)) {
                            if (!KiteStringUtils.isEqual("200000172", instAttrDTO.getFieldName())) {
                                instAttrDTO.setIsEdit(KeyConsts.IFTRUE_F);
                            }
                        }
                    }
                }
                instAttrDTOList.add(instAttrDTO);
            }
        });
        cuccProdSubOfferVO.setInstAttrDTOS(instAttrDTOList);
        DataResult<CuccProdSubOfferVO> result = ErrorConsts.SUCCESS.getResult(cuccProdSubOfferVO);
        return result;
    }

    @KiteTransactional
    @ApiOperation(value = "删除资费", notes = "删除资费")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "deleteAdditionalOfferListParamVO", value = "删除资费入参对象", required = true)
    })
    @DeleteMapping(value = "/deleteAdditionalOfferList")
    public DataResult<Boolean> deleteAdditionalOfferList(@RequestBody DeleteAdditionalOfferListParamVO deleteAdditionalOfferListParamVO) {
        List<String> offerInstIdList = deleteAdditionalOfferListParamVO.getOfferInstIdList();
        String sceneInstId = deleteAdditionalOfferListParamVO.getSceneInstId();
        if (KiteListUtils.isEmpty(offerInstIdList)) {
            return ErrorConsts.SUCCESS.getResult(true);
        }
        String custId = KiteWebContext.getContext().getCustId();
        offerInstIdList.stream().forEach(t -> {
            operateSceneAdditionalOfferInstService.removeAdditionalOfferInst(sceneInstId, t, custId, null);
        });


        /**
         * 资费校验规则埋点-start
         */
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        RuleCommonParam ruleCommonParam = RuleParamUtils.getRuleParam(sceneInst.getCustId());
        cuccCheckService.checkOfferInstFeeList(sceneInst.getSceneInstId(), ruleCommonParam);
        /**
         * 资费校验规则埋点-end
         */
        sceneInstOperateService.putExtParameter(sceneInstId, LocalAdditionalOfferUtils.OFFERINSTIDS, null);
        LocalWholeQuickEntryCache.delete(sceneInstId);

        return ErrorConsts.SUCCESS.getResult(true);
    }

    @KiteTransactional
    @ApiOperation(value = "还原资费产品属性", notes = "编辑时，点击取消按钮，将编辑前的值还原")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "offerInstId", value = "资费产品实例标识", required = true)
    })
    @PostMapping(value = "/restore")
    public DataResult<Boolean> restoreAdditionalOfferInstAttr(@RequestParam String offerInstId) {
        String sceneInstId = KiteWebContext.getContext().getCurrentSceneInstId();
        String custId = KiteWebContext.getContext().getCustId();
        KiteOfferInst offerInst = querySceneInstService.getOfferInst(custId, offerInstId);
        IOperateSceneInstService operateSceneInstService = SpringUtil.getBean(IOperateSceneInstService.class);
        List<KiteAttr> kiteAttrList = querySceneInstService.getExtParameterValue(sceneInstId, offerInstId);
        if (KiteListUtils.isEmpty(kiteAttrList)) {
            return ErrorConsts.SUCCESS.getResult(Boolean.TRUE);
        }
        operateSceneInstService.setAttrs(sceneInstId, offerInst.getInstType(), offerInstId, kiteAttrList);
        return ErrorConsts.SUCCESS.getResult(Boolean.TRUE);
    }

    @KiteTransactional
    @ApiOperation(value = "资费作废", notes = "资费作废")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "offerInstId", value = "资费产品实例标识", required = true)
    })
    @PostMapping(value = "/cancel")
    public DataResult<Boolean> cancelAdditionalOfferInst(@RequestParam String offerInstId) {
        String sceneInstId = KiteWebContext.getContext().getCurrentSceneInstId();
        String custId = KiteWebContext.getContext().getCustId();
        KiteOfferInst offerInst = querySceneInstService.getOfferInst(custId, offerInstId);
        IOperateSceneInstService operateSceneInstService = SpringUtil.getBean(IOperateSceneInstService.class);
        List<KiteAttr> kiteAttrList = offerInst.listAttrs();
        kiteAttrList.forEach(attr -> {
            if (KiteStringUtils.isEqual(attr.getFieldName(), LocalKeyConsts.END_DATE_FIELD_NAME)) {
                String newEndDate = DateFormatUtils.formatDate(KiteDateUtils.getEndOfLastDay(), DateFormatUtils.DATE_TIME_FORMAT);
                attr.setValue(newEndDate);
            }
        });
        operateSceneInstService.setAttrs(sceneInstId, offerInst.getInstType(), offerInstId, kiteAttrList);
        offerInst.setOriginalActionType(offerInst.getActionType());
        offerInst.setActionType(ActionType.C);
        operateSceneInstService.addAdditionalOfferInst(sceneInstId, offerInst);

        /**
         * 资费校验规则埋点-start
         */
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        RuleCommonParam ruleCommonParam = RuleParamUtils.getRuleParam(sceneInst.getCustId());
        cuccCheckService.checkOfferInstFeeList(sceneInst.getSceneInstId(), ruleCommonParam);
        /**
         * 资费校验规则埋点-end
         */


        return ErrorConsts.SUCCESS.getResult(Boolean.TRUE);
    }

    @KiteTransactional
    @ApiOperation(value = "资费还原", notes = "还原置最原始状态")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "offerInstId", value = "资费产品实例标识", required = true)
    })
    @PostMapping(value = "/restoreCancel")
    public DataResult<Boolean> restoreCancelAdditionalOfferInst(@RequestParam String offerInstId) {
        String sceneInstId = KiteWebContext.getContext().getCurrentSceneInstId();
        String custId = KiteWebContext.getContext().getCustId();
        KiteOfferInst offerInst = querySceneInstService.getOfferInst(custId, offerInstId);
        IOperateSceneInstService operateSceneInstService = SpringUtil.getBean(IOperateSceneInstService.class);
        List<KiteAttr> kiteAttrList = offerInst.listAttrs();
        kiteAttrList.forEach(attr -> {
            attr.setValue(attr.getOriginValue());
        });
        operateSceneInstService.setAttrs(sceneInstId, offerInst.getInstType(), offerInstId, kiteAttrList);
        offerInst.setActionType(ActionType.K);
        operateSceneInstService.addAdditionalOfferInst(sceneInstId, offerInst);


        /**
         * 资费校验规则埋点-start
         */
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        RuleCommonParam ruleCommonParam = RuleParamUtils.getRuleParam(sceneInst.getCustId());
        cuccCheckService.checkOfferInstFeeList(sceneInst.getSceneInstId(), ruleCommonParam);
        /**
         * 资费校验规则埋点-end
         */

        return ErrorConsts.SUCCESS.getResult(Boolean.TRUE);
    }

    @ApiOperation(value = "根据场景实例Id获取页面展示模块对象", notes = "根据场景实例Id获取页面展示模块对象")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "sceneInstId", value = "场景实例标识", required = true)
    })
    @GetMapping(value = "/additionalOfferModuleVO")
    public DataResult<Map<String, Object>> queryAdditionalOfferModuleVO(@RequestParam String sceneInstId) {
        Map<String, Object> result = new HashMap<>();
        String bizType = querySceneInstService.getExtParameterValue(sceneInstId, "bizType");
        if (KiteStringUtils.equalsAny(bizType, "1003", "1004", "1048")) {
            ShutdownAdditionalOfferModuleHandler handler = SpringUtil.getBean(ShutdownAdditionalOfferModuleHandler.class);
            Map<String, OptionalAdditionalOfferModuleVO> additionalOfferModuleVO = handler.getOptionalAdditionalOfferModuleVO(sceneInstId, false);
            result.put("additionalOffers", additionalOfferModuleVO);
        } else {
            OptionalAdditionalOfferModuleHandler handler = SpringUtil.getBean(OptionalAdditionalOfferModuleHandler.class);
            Map<String, OptionalAdditionalOfferModuleVO> additionalOfferModuleVO = handler.getOptionalAdditionalOfferModuleVO(sceneInstId, false);
            result.put("additionalOffers", additionalOfferModuleVO);
        }

        return ErrorConsts.SUCCESS.getResult(result);
    }

    @KiteTransactional
    @ApiOperation(value = "根据全程议价快捷配置资费参数", notes = "根据全程议价快捷配置资费参数")
    @PostMapping(value = "/wholeQuickEntrySave")
    public DataResult<List<CuccPayAddtionOfferVO>> wholeQuickEntryAttr(@RequestBody WholeQuickEntryVO wholeQuickEntryVO) {
        List<String> offerInstIds = querySceneInstService.getExtParameterValue(wholeQuickEntryVO.getWholeQuickEntryId(), LocalAdditionalOfferUtils.OFFERINSTIDS);
        Map<String, String> kiteAttrMap = wholeQuickEntryVO.getKiteAttrs().stream().collect(Collectors.toMap(KiteAttr::getFieldName, KiteAttr::getValue));
        //组装返回数据
        List<CuccPayAddtionOfferVO> cuccPayAddtionOfferVOS = new ArrayList<>();
        cuccPayAddtionOfferVOS.add(new CuccPayAddtionOfferVO());
        cuccPayAddtionOfferVOS.get(0).setWholeQuickEntryVO(wholeQuickEntryVO);
        List<CuccOfferVO> cuccOfferVOS = new ArrayList<>();
        BigDecimal valueCount = new BigDecimal(0);
        for (int k = 0; k < offerInstIds.size(); k++) {
            CuccOfferVO cuccOfferVO = new CuccOfferVO();
            KiteOfferInst kiteOfferInst = new KiteOfferInst();
            kiteOfferInst.setOfferInstId(offerInstIds.get(k));
            for (KiteAttr kiteAttr : wholeQuickEntryVO.getKiteAttrs()) {
                if (KiteStringUtils.equalsAny(kiteAttr.getFieldName(), LocalAdditionalOfferUtils.ZHEKOU, LocalAdditionalOfferUtils.PEIZHIFEIYONG)) {
                    continue;
                }
                if (kiteAttr.getFieldName().equals(LocalAdditionalOfferUtils.XIEYIJIA)) {
                    //根据协议价配置协议月租
                    if (StringUtils.isNotEmpty(kiteAttrMap.get(LocalAdditionalOfferUtils.PEIZHIFEIYONG))) {
                        BigDecimal b = new BigDecimal(wholeQuickEntryVO.getRatio().get(k));
                        BigDecimal value = new BigDecimal(kiteAttr.getValue());
                        if (k > 1 && k == offerInstIds.size() - 1) {
                            saveAdditionalOfferAttrs(kiteOfferInst, "200000169", value.subtract(valueCount).setScale(2, RoundingMode.HALF_UP).toString(), kiteAttr.getValueDesc());
                        } else {
                            BigDecimal bigDecimal = value.multiply(b).setScale(2, RoundingMode.HALF_UP);
                            valueCount = valueCount.add(bigDecimal);
                            saveAdditionalOfferAttrs(kiteOfferInst, "200000169", bigDecimal.toString(), kiteAttr.getValueDesc());
                        }
                    }
                } else {
                    saveAdditionalOfferAttrs(kiteOfferInst, kiteAttr.getFieldName(), kiteAttr.getValue(), kiteAttr.getValueDesc());

                }
            }
            Map<String, KiteAttr> kiteAttrs = listOfferInstAttrs(kiteOfferInst);
            //置灰处理
            for (String fieldName : LocalAdditionalOfferUtils.fieldNames) {
                if (null != kiteAttrs.get(fieldName)) {
                    kiteAttrs.get(fieldName).setIsEdit("F");
                }
            }
            kiteOfferInst.setAttrMap(kiteAttrs);
            cuccOfferVO.setOfferInst(Arrays.asList(kiteOfferInst));
            cuccOfferVOS.add(cuccOfferVO);
        }
        cuccPayAddtionOfferVOS.get(0).getOfferVOList().addAll(cuccOfferVOS);
        LocalWholeQuickEntryCache.put(wholeQuickEntryVO.getWholeQuickEntryId(), wholeQuickEntryVO);
        return ErrorConsts.SUCCESS.getResult(cuccPayAddtionOfferVOS);
    }

    @KiteTransactional
    @ApiOperation(value = "全程议价快捷录入区域信息修改", notes = "全程议价快捷录入区域信息修改")
    @PostMapping(value = "/wholeQuickEntryAttr")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "type", value = "单选0折扣,1议价", required = true),
        @ApiImplicitParam(name = "sceneInstId", value = "资费产品实例标识", required = true),
        @ApiImplicitParam(name = "fieldName", value = "资费产品实例标识"),
        @ApiImplicitParam(name = "value", value = "资费产品实例标识"),
        @ApiImplicitParam(name = "valueDesc", value = "资费产品实例标识")
    })
    public DataResult<WholeQuickEntryVO> wholeQuickEntryAttr(int type, String sceneInstId, String fieldName, String value, String valueDesc) {
        WholeQuickEntryVO wholeQuickEntryVO = LocalWholeQuickEntryCache.get(sceneInstId);
        wholeQuickEntryVO.setType(type);
        Map<String, String> kiteAttrMap = wholeQuickEntryVO.getKiteAttrs().stream().collect(Collectors.toMap(KiteAttr::getFieldName, KiteAttr::getValue));
        //点选type设置属性
        if (StringUtils.isEmpty(fieldName)) {
            wholeQuickEntryVO.getKiteAttrs().forEach(kiteAttr -> {
                if (type == 1) {
                    if (kiteAttr.getFieldName().endsWith(LocalAdditionalOfferUtils.ZHEKOU)) {
                        kiteAttr.setIsEdit("F");
                    }
                    if (kiteAttr.getFieldName().endsWith(LocalAdditionalOfferUtils.XIEYIJIA)) {
                        kiteAttr.setIsEdit("T");
                    }
                }
                if (type == 0) {
                    if (kiteAttr.getFieldName().endsWith(LocalAdditionalOfferUtils.XIEYIJIA)) {
                        kiteAttr.setIsEdit("F");
                    }
                    if (kiteAttr.getFieldName().endsWith(LocalAdditionalOfferUtils.ZHEKOU)) {
                        kiteAttr.setIsEdit("T");
                    }
                }
            });
            LocalWholeQuickEntryCache.put(sceneInstId, wholeQuickEntryVO);
            return ErrorConsts.SUCCESS.getResult(wholeQuickEntryVO);
        }
        //协议价折扣单独处理
        if (StringUtils.isNotEmpty(kiteAttrMap.get(LocalAdditionalOfferUtils.PEIZHIFEIYONG))) {
            if (LocalAdditionalOfferUtils.XIEYIJIA.equals(fieldName) && type == 1) {
                BigDecimal valueB = new BigDecimal(value);
                if (valueB.compareTo(new BigDecimal(kiteAttrMap.get(LocalAdditionalOfferUtils.PEIZHIFEIYONG))) == 1) {
                    String message = "全程协议价超过标准配置费用，请核对!";
                    wholeQuickEntryVO.setReminder(message);
//                    ErrorConsts.BUSI_COMMON_ERROR.throwOut("全程协议价不能大于配置费用，请重新填写！");
                } else {
                    wholeQuickEntryVO.setReminder(null);
                }
                wholeQuickEntryVO.getKiteAttrs().forEach(kiteAttr -> {
                    if (kiteAttr.getFieldName().endsWith(LocalAdditionalOfferUtils.ZHEKOU)) {
                        BigDecimal bigDecimal = new BigDecimal(DecimalCalc.div(value, kiteAttrMap.get(LocalAdditionalOfferUtils.PEIZHIFEIYONG)));
                        String divValue = String.valueOf(bigDecimal.setScale(2, RoundingMode.HALF_UP));
                        kiteAttr.setValue(divValue);
                        kiteAttr.setValueDesc(divValue);
                        kiteAttr.setIsEdit("F");
                    }
                });
            } else {
                wholeQuickEntryVO.setReminder(null);
            }
            if (LocalAdditionalOfferUtils.ZHEKOU.equals(fieldName) && type == 0) {
                if (checkZheKou(value)) {
                    String message = "全程协议格超过标准配置费用，请核对!";
                    wholeQuickEntryVO.setReminder(message);
                } else {
                    wholeQuickEntryVO.setReminder(null);
                }
                wholeQuickEntryVO.getKiteAttrs().forEach(kiteAttr -> {
                    if (kiteAttr.getFieldName().endsWith(LocalAdditionalOfferUtils.XIEYIJIA)) {
                        String mulValue = DecimalCalc.mulBigDecimal(value, kiteAttrMap.get(LocalAdditionalOfferUtils.PEIZHIFEIYONG)).setScale(2, RoundingMode.HALF_UP).toString();
                        kiteAttr.setValue(mulValue);
                        kiteAttr.setValueDesc(mulValue);
                        kiteAttr.setIsEdit("F");
                    }
                });

            }
        }
        wholeQuickEntryVO.getKiteAttrs().forEach(kiteAttr -> {
            if (kiteAttr.getFieldName().equals(fieldName)) {
                kiteAttr.setValue(value);
                kiteAttr.setValueDesc(valueDesc);
            }
        });
        wholeQuickEntryVO.setKiteAttrs(LocalAdditionalOfferUtils.dealLinkAttr(wholeQuickEntryVO.getKiteAttrs(), fieldName, value));
        LocalWholeQuickEntryCache.put(sceneInstId, wholeQuickEntryVO);
        return ErrorConsts.SUCCESS.getResult(wholeQuickEntryVO);
    }

    private void saveAdditionalOfferAttrs(KiteOfferInst inst, String fieldName, String attrValue, String valueDesc) {
        String sceneInstId = KiteWebContext.getContext().getCurrentSceneInstId();
        String custId = KiteWebContext.getContext().getCustId();
        LoginInfo loginInfo = ContextUtil.getLoginInfo();
        String staffId = loginInfo.getUserInfo().getUserId() + "";
        KiteOfferInst offerInst = querySceneMainOfferInstService.getOfferInst(custId, inst.getOfferInstId());
        RuleCommonParam ruleParam = RuleParamUtils.getRuleParam();
        String oldValue = Optional.ofNullable(offerInst.getAttrMap()).map(m -> m.get(fieldName)).map(t -> t.getValue())
            .orElse("");
        String offerId = offerInst.getOfferId();
        String serviceOfferId = querySceneInstService.getSceneInst(sceneInstId).getServiceOfferId();
        InstAttrChange change = RuleParamUtils
            .getInstAttrChange(serviceOfferId, RuleConsts.TYPE_1004, KeyConsts.OFFER_TYPE_12, inst.getOfferInstId(), offerId,
                BusiConfigTables.OFFER_INST.name(), fieldName, oldValue, attrValue);

        //修改销售品属性规则
        KiteRuleResponse bfRuleResponse = ruleTriggerService.onBfOfferAttrModRule(sceneInstId, change, ruleParam);
        DataRuleResult bfRuleResult = RuleResponseUtils.transRuleResponse2RuleResult(bfRuleResponse);
        if (RuleConsts.RULE_RESPONSE_FAILURE.equals(bfRuleResult.getResultCode()) || !bfRuleResult.getResultObject()
            .getCheckFlag()) {
            RuleResponseUtils.cheackRuleResp(bfRuleResponse);
            //            return ErrorConsts.SUCCESS.getResult(null, bfRuleResult);
        }
        operateSceneAdditionalOfferInstService
            .updateAdditionalOfferAttr(sceneInstId, inst.getOfferInstId(), fieldName, attrValue, valueDesc, custId, staffId);
        KiteOfferInst additionalKiteOfferInst = querySceneInstService.getOfferInst(custId, inst.getOfferInstId());
        if (Objects.nonNull(additionalKiteOfferInst) && KiteStringUtils.isEqual(additionalKiteOfferInst.getActionType().name(), ActionType.K.name())) {
            additionalKiteOfferInst.setActionType(ActionType.M);
            sceneInstOperateService.addAdditionalOfferInst(sceneInstId, additionalKiteOfferInst);
        }

        KiteRuleResponse afRuleResponse = ruleTriggerService.onAfOfferAttrModRule(sceneInstId, change, ruleParam);
        DataRuleResult afRuleResult = RuleResponseUtils.transRuleResponse2RuleResult(afRuleResponse);

        if (RuleConsts.RULE_RESPONSE_FAILURE.equals(afRuleResult.getResultCode()) || !afRuleResult.getResultObject()
            .getCheckFlag()) {
            RuleResponseUtils.cheackRuleResp(afRuleResponse);
            //            return ErrorConsts.SUCCESS.getResult(null, afRuleResult);
        }
    }

    private Map<String, KiteAttr> listOfferInstAttrs(KiteOfferInst inst) {
        String sceneInstId = KiteWebContext.getContext().getCurrentSceneInstId();
        DataResult<List<InstAttrDTO>> dataResult = querySceneAdditionalOfferInstService
            .listAdditionalOfferInstAttrsByOfferInstId(sceneInstId, inst.getOfferInstId(),
                KiteWebContext.getContext().getCustId());
        List<InstAttrDTO> dtoList = dataResult.getResultObject();
        dtoList = KiteListUtils.isEmpty(dtoList)
            ? dtoList
            : dtoList.stream().filter(v -> !KeyConsts.PROD_ATTR_SHOW_TYPE_E.equals(v.getShowType()))
            .collect(Collectors.toList());
        return transferValue(dtoList);
    }

    private Map<String, KiteAttr> transferValue(List<InstAttrDTO> attrDTOS) {
        List<KiteAttr> kiteAttrs = KiteBeanUtils.copyPropsForList(attrDTOS, KiteAttr.class);
        return kiteAttrs.stream().collect(Collectors.toMap(KiteAttr::getFieldName, kiteAttr -> kiteAttr));
    }

    private boolean checkZheKou(String value) {
        BigDecimal bigDecimal = new BigDecimal(value);
        if (bigDecimal.compareTo(BigDecimal.ONE) == 1) {
            return true;
        } else if (bigDecimal.compareTo(BigDecimal.ONE) == 0) {
            return false;
        } else if (KiteStringUtils.equalsAny("1.0", "1.00")) {
            return false;
        } else {
            if (value.length() > 4) {
                return true;
            }
            return false;
        }

    }

}
